package driver;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import classes.*;
import driver.Utilitats.DiesSetmanaABR;

public class GenerarAgendaA implements GeneradorAgenda {

	private Agenda agenda;
	private Configuracio configuracioActual;
	


	public GenerarAgendaA(ArrayList<Comanda> comandes,
			Configuracio configuracioActual) {
		Calendari auxCalendari;
		Calendari calendariTemporal;
		this.configuracioActual = configuracioActual;
		agenda = new Agenda();
		
		
		
		int contadorComandesIntroduides=0;
		
		
		for (Comanda auxComanda : comandes) {
			//System.out.println(auxComanda);
			if (auxComanda.getActivitat().getClass().equals(ActivitatTancat.class)) {
				calendariTemporal = processarEspai(auxComanda);

				processarTancats(auxComanda, calendariTemporal);
				
				if (auxComanda.isIntroduida()){
					agenda.substituirEspai(auxComanda.getEspai());
					contadorComandesIntroduides++;
					Log.llenarLog("Introduida comanda:");
					Log.llenarLog(auxComanda.toString());
				}else{
					Log.llenarLog("Comanda no Introduida :");
					Log.llenarLog(auxComanda.toString());
				}
			}
		}
		
		
		for (Comanda auxComanda : comandes) {
			Activitat auxActivitatProcessada = auxComanda.getActivitat();

			if (!auxActivitatProcessada.getClass().equals(ActivitatTancat.class)) {

				for (Comanda auxComandaProcesant : comandes) {
					if (auxActivitatProcessada.equals(auxComandaProcesant
							.getActivitat())) {   
						
					calendariTemporal = processarEspai(auxComanda);

						int cont = 0;  
						
						cont = inserirActivitatCalendari(calendariTemporal,
								auxComanda.getActivitat(),
								auxComanda.getDataIni(),
								auxComanda.getDataFi(),
								auxComanda.getDiesSetmana(),
								auxComanda.getPlantillaHores());
						
						if (cont>0){   
							Espai auxEspai=auxComanda.getEspai();
							auxEspai.assignarCalendari(calendariTemporal);
							agenda.substituirEspai(auxEspai);
							auxComanda.setIntroduida(true);
							
							
							contadorComandesIntroduides++;
							Log.llenarLog("S'han inserit " + cont + " registres de la comanda:");
							Log.llenarLog(auxComanda.toString() + "\n");
							System.out.println("S'han inserit " + cont + " registres de la comanda");
						
						}else{
							auxComanda.setIntroduida(false);
							Log.llenarLog("No s'han afegit registres d'aquesta comanda: ");
							Log.llenarLog(auxComanda.toString());
							System.out.println("No s'han afegit registres d'aquesta comanda. ");
						}
						
						break;
					}
				}
			}
		}

		// comanda.getMes(); //

	}

	private void processarTancats(Comanda auxComanda, Calendari auxCalendari) {
		int cont = 0;

		cont = inserirActivitatCalendari(auxCalendari,
				auxComanda.getActivitat(), auxComanda.getDataIni(),
				auxComanda.getDataFi(), auxComanda.getDiesSetmana(),
				auxComanda.getPlantillaHores());
		
		if (cont > 0) {
			Espai auxEspai=auxComanda.getEspai();
			
			auxEspai.assignarCalendari(auxCalendari);
			agenda.assignarEspai(auxEspai);
			
			auxComanda.setIntroduida(true);
		}else{
			auxComanda.setIntroduida(false);
		}
	}

	private int inserirActivitatCalendari(Calendari auxCalendari,
			Activitat activitat, Calendar dataIni, Calendar dataFi,
			DiesSetmanaABR[] diesSetmana, Dia plantillaHores) {

		// Filtrar mes
		int cont=0;
		filtrarMes(dataIni, dataFi);

		Mes plantillaMes = crearMes(dataIni, dataFi, diesSetmana);
		//System.out.println(plantillaMes);
		//System.out.println(plantillaHores);
		cont = afegirHores(auxCalendari, plantillaMes, plantillaHores,
				activitat);
		
		

		return cont;
	}


	private int afegirHores(Calendari auxCalendari, Mes plantillaMes, Dia plantillaHores, Activitat activitat) {
		
		int contadorActivitatsAfegides=0;
		boolean trobat=false;
		

		Any auxAny = auxCalendari.getAny(configuracioActual.getAny());

		
		if (auxAny==null){
			auxAny= new Any(configuracioActual.getAny(),configuracioActual.getMes());
			contadorActivitatsAfegides+= plantillaMes.afegirActivitatPlantillaMes(activitat,plantillaMes,plantillaHores);
			auxAny.setMes(configuracioActual.getMes(),plantillaMes);
			
		}else{
			
			Mes auxMes = auxAny.getMes(configuracioActual.getMes());
			if (plantillaMes.equals(auxMes)){
				
				contadorActivitatsAfegides+= auxMes.afegirActivitatPlantillaMes(activitat,plantillaMes,plantillaHores);
			}
		}

		

		return contadorActivitatsAfegides;
	}

	private Mes crearMes(Calendar dataIni, Calendar dataFi,
			DiesSetmanaABR[] diesSetmana) {
		
		SimpleDateFormat df = new SimpleDateFormat();
		df.applyPattern("dd/MM/yyyy");
		//System.out.println(df.format(dataCal.getTime()));
		

		Mes mes = new Mes(configuracioActual.getMes());

		for (DiesSetmanaABR dia : diesSetmana) {

			Calendar dataAux = Calendar.getInstance();

			// Copiem dataIni a dataAux per fer iteracions
			dataAux.setTime(dataIni.getTime());
			
			//System.out.println(df.format(dataIni.getTime()));
			//System.out.println(df.format(dataAux.getTime()));
			
			while (dataAux.compareTo(dataFi) <= 0) {

				// FUNCIONA NOM�S SI LA ENUM DIESETMANAABR comen�a en DIUMENGE

				if (dataAux.get(Calendar.DAY_OF_WEEK) == (dia.ordinal()) + 1) {

					Dia d = new Dia((dataAux.get(Calendar.DATE)));
					mes.afegirDia(d);
					//System.out.println(d.getNumDia());
				}

				dataAux.add(Calendar.DATE, 1);
			}

		}

		return mes;

	}

	private void filtrarMes(Calendar dataIni, Calendar dataFi) {

		
		Calendar dataCal = Calendar.getInstance();

		// Agafem Mes i Any de Config.
		dataCal.set(configuracioActual.getAny(),
				configuracioActual.getMes(),
				dataCal.getMinimum(Calendar.DATE));

		// Comprobaci� si data VALIDA
		if (dataIni.before(dataFi) && dataFi.after(dataCal)) {

			// Si dataIni no est� al Mes Config. data Ini = Primer dia del mes
			// Config.
			if (dataIni.get(Calendar.MONTH) != dataCal.get(Calendar.MONTH)) {
				dataIni.set(dataCal.get(Calendar.YEAR),
						dataCal.get(Calendar.MONTH),
						dataIni.getActualMinimum(Calendar.DATE));
			} else {
				dataIni.set(dataCal.get(Calendar.YEAR),
						dataCal.get(Calendar.MONTH), dataIni.get(Calendar.DATE));
			}

			// Si dataFi no est� al Mes Config. data Fi = Ultim dia del mes
			// Config.
			
			if (dataFi.get(Calendar.MONTH) != dataCal.get(Calendar.MONTH)) {

				dataFi.set(dataCal.get(Calendar.YEAR),
						dataCal.get(Calendar.MONTH),
						dataIni.getActualMaximum(Calendar.DATE));
			} else {

				dataFi.set(dataCal.get(Calendar.YEAR),
						dataCal.get(Calendar.MONTH), dataFi.get(Calendar.DATE));
			}
		}

		else { // TODO: Incloure Exception
			// throw new Exception("Data No VALIDA");
			//Log.llenarLog("Data no valida");
		}

	}

	
	private Calendari processarEspai(Comanda auxComanda) {
		Espai  nomEspai= auxComanda.getEspai();
		Calendari auxCalendari = new Calendari(configuracioActual.getAny(),configuracioActual.getMes());
		
		if (agenda.contiene(nomEspai)) {
			auxComanda.setEspai(agenda.getEspai(nomEspai));
			
			auxCalendari.merge(agenda.getEspai(nomEspai).getCal());
		} else {
			nomEspai.assignarCalendari(auxCalendari);
		}
		return auxCalendari;
		
	}

	@Override
	public Agenda getAgenda() {
		// TODO Auto-generated method stub
		return agenda;
	}

}
